export function clone<T>(obj: T): T {
    let value: any = obj;
    let type = Object.prototype.toString.call(value);
    if(type == "[object Array]") {
        let res = [];
        for(let item of value) {
            res.push(clone(item));
        }
        return <any>res;
    }
    if(type == '[object Object]') {
        let res: {[key: string]: any} = {};
        for(let key in value) {
            res[key] = clone(value[key]);
        }
        return <any>res;
    }
    if(type == '[object Date]') {
        let date =  new Date(value.getTime());
        return <any>date;
    }
    if(type == '[object RegExp]') {
        return <any>(new RegExp(value));
    }
    return obj;
}
export function coverObj<T>(originObj: Partial<T>,...objs: Partial<T>[]): T {
    for(let obj of objs) {
        for(let key in obj) {
            if(originObj.hasOwnProperty(key) == false) {
                originObj[key] = obj[key];
            } else {
                let type = Object.prototype.toString.call(obj[key]);
                if(type == '[object Object]') {
                    originObj[key] = coverObj(originObj[key], obj[key]);
                } else {
                    originObj[key] = obj[key];
                }
            }
        }
    }
    return <T>originObj;
}
export function getPixelRatio(ctx: CanvasRenderingContext2D) {
    let context: any = ctx;
    var backingStore = context.backingStorePixelRatio ||
    context.webkitBackingStorePixelRatio ||
    context.mozBackingStorePixelRatio ||
    context.msBackingStorePixelRatio ||
    context.oBackingStorePixelRatio ||
    context.backingStorePixelRatio || 1;
    return (window.devicePixelRatio || 1) / backingStore;
}
export function setCanvasSize(ele: HTMLCanvasElement): {width: number, height: number} {
    let ctx = ele.getContext('2d');
    let ratio = getPixelRatio(ctx);
    // if(ele.clientHeight * ratio == 0) {
    //     ele.height = def.height
    // } else {
        ele.height = ele.clientHeight * ratio;
    // }
    // if(ele)
    ele.width = ele.clientWidth * ratio;
    return {width: ele.width, height: ele.height}
}
export function createBlockImage(width: number, height: number) {
    const canvas = document.createElement('canvas') as HTMLCanvasElement;
    canvas.height = height;
    canvas.width = width;
    const ctx = canvas.getContext('2d');
    ctx.beginPath();
    ctx.rect(0, 0, width / 2, height / 2);
    ctx.closePath();
    ctx.fillStyle = 'rgba(0,0,0,0.3)';
	ctx.fill();
    ctx.restore();

    ctx.beginPath();
    ctx.rect(width / 2, 0, width / 2, height / 2);
    ctx.closePath();
    ctx.fillStyle = '#ffffff';
	ctx.fill();
    ctx.restore();

    ctx.beginPath();
    ctx.rect(0, height / 2, width / 2, height / 2);
    ctx.closePath();
    ctx.fillStyle = '#ffffff';
	ctx.fill();
    ctx.restore();
    
    ctx.beginPath();
    ctx.rect(width / 2, height / 2, width / 2, height / 2);
    ctx.closePath();
    ctx.fillStyle = 'rgba(0,0,0,0.3)';
	ctx.fill();
    ctx.restore();
    return canvas.toDataURL('image/png');
}
export function getCanvasImage() {

}
export function limitThrowError(max = 10000) {
    if(__ENV__ === 'development') {
        let currentCount = 0;
        const maxBreakCount = max;
        return () => {
            currentCount++;
            if(currentCount > maxBreakCount) {
                throw new Error('max limitError');
            }
        }
    } else {
        return () => {

        }
    }
}
export function isEqualArr(arr1: any[], arr2: any[]) {
    if(arr1.length !== arr2.length) {
        return false;
    }
    for(let i = 0; i < arr1.length; i++) {
        if(arr1[i] !== arr2[i]) {
            return false;
        }
    }
    return true;
}
export function catchFunc<T extends Function>(func: T) {
    let res: any = void 0;
    let pastDeps: any[] = [];
    let pastArgs: any[] = [];
    return (deps: any[], ...args: any[]) => {
        if(res === void 0 || !isEqualArr(pastArgs, args) || !isEqualArr(pastDeps, deps)) {
            pastDeps = deps;
            pastArgs = args;
            res = func(...args);
            return res;
        } else {
            return res;
        }
    }
}

export function equalMerge(merge1: TRange, merge2: TRange) {
    return (merge1.row === merge2.row && merge1.col === merge2.col && merge1.rowspan === merge2.rowspan && merge1.colspan === merge2.colspan);
}
export const safeWhile = (func: (idx: number) => boolean, max = 1000) => {
    let idx = 0;
    while(true) {
        let manualBreck = func(idx);
        if(idx++ === max || manualBreck) {
            break;
        }
    }
}

export function equalRange(range1: TRange, range2: TRange) {
    return (range1.row === range2.row && range1.col === range2.col && range1.rowspan === range2.rowspan && range1.colspan === range2.colspan);
}

/**
 * @describe targetRange contain sourceRange
 * @param targetRange position, fullRow, fullCol
 * @param sourceRange position, fullRow, fullCol
 */
export const isContainRange = (targetRange: TRange, sourceRange: TRange) => {
    // full col
    if(targetRange.col === -1 || targetRange.colspan === -1) {
        return sourceRange.row >= targetRange.row && sourceRange.row + sourceRange.rowspan <= targetRange.row + targetRange.rowspan;
    }
    if(targetRange.row === -1 || targetRange.rowspan === -1) {
        return sourceRange.col >= targetRange.col && sourceRange.col + sourceRange.colspan <= targetRange.col + targetRange.colspan;
    }
    return sourceRange.row >= targetRange.row && sourceRange.row + sourceRange.rowspan <= targetRange.row + targetRange.rowspan
    && sourceRange.col >= targetRange.col && sourceRange.col + sourceRange.colspan <= targetRange.col + targetRange.colspan;
}
